//-----------------------------------------------------------------------
// <copyright file="Actions.cs" company="Robert MacLean">
//     This file is released under the LGPL. For more information see 
//     http://gallery2.codeplex.com.
//     Originally created by Robert MacLean http://www.sadev.co.za
// </copyright>
//-----------------------------------------------------------------------

namespace SADev.Gallery2.Protocol
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Net;

    /// <summary>
    /// Actions provides a wrap for the G2 Remote Protocol
    /// </summary>
    public class Actions
    {
        /// <summary>
        /// The G2Request object to use.
        /// </summary>
        private G2Request request = new G2Request();

        /// <summary>
        /// The server host to connect to.
        /// </summary>
        private string host;

        /// <summary>
        /// Initializes a new instance of the <see cref="Actions"/> class.
        /// </summary>
        /// <param name="host">The host server name and path.</param>
        public Actions(string host)
        {
            this.host = host;
            this.request.Host = host;
        }

        /// <summary>
        /// Logs the user in with the  the specified username/password.
        /// </summary>
        /// <param name="userName">The username.</param>
        /// <param name="password">The password.</param>
        /// <returns>A LogOnResponse containing the responses/details.</returns>
        public LogOnResponse LogOn(string userName, string password)
        {
            Dictionary<string, string> values = new Dictionary<string, string>();
            values.Add("Username", userName);
            values.Add("Password", password);
            return new LogOnResponse(this.request.Execute(Commands.Login, values));
        }

        /// <summary>
        /// Executes a NoOp, which is basically a test that does nothing.
        /// </summary>
        /// <returns>A NoOpResponse containing the responses/details.</returns>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1709:IdentifiersShouldBeCasedCorrectly", MessageId = "Op", Justification = "NoOp is correctly cased")]
        public NoOpResponse NoOp()
        {
            return new NoOpResponse(this.request.Execute(Commands.NoOp, null));
        }

        /// <summary>
        /// Fetches the albums.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <returns>A FetchAlbumResponse containing the responses/details.</returns>
        public FetchAlbumResponse FetchAlbums(string authToken)
        {
            return this.FetchAlbums(authToken, false);
        }

        /// <summary>
        /// Fetches the albums.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <param name="excludeAlbumPermissions">if set to <c>true</c> [exclude album permissions].</param>
        /// <returns></returns>
        public FetchAlbumResponse FetchAlbums(string authToken, bool excludeAlbumPermissions)
        {
            Dictionary<string, string> values = new Dictionary<string, string>();
            values.Add("Exclude Album Permissions", excludeAlbumPermissions.ToG2Value());
            return new FetchAlbumResponse(this.request.Execute(Commands.FetchAlbums, values, authToken));
        }

        /// <summary>
        /// Fetches the images from an album.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <param name="albumName">Name of the album.</param>
        /// <returns>A FetchAlbumImagesResponse containing the responses/details.</returns>
        public FetchAlbumImagesResponse FetchImages(string authToken, string albumName)
        {
            return this.FetchImages(authToken, albumName, false, false, 0, false, true);
        }

        /// <summary>
        /// Fetches the images.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <param name="albumName">Name of the album.</param>
        /// <param name="includeAlbums">if set to <c>true</c> [include albums].</param>
        /// <param name="random">if set to <c>true</c> [random].</param>
        /// <param name="limit">The limit to get, set to 0 to get all.</param>
        /// <param name="extraFields">if set to <c>true</c> [extra fields].</param>
        /// <param name="allSizes">if set to <c>true</c> [all sizes].</param>
        /// <returns>A FetchAlbumImagesResponse containing the responses/details.</returns>
        public FetchAlbumImagesResponse FetchImages(string authToken, string albumName, bool includeAlbums, bool random, int limit, bool extraFields, bool allSizes)
        {
            Dictionary<string, string> values = new Dictionary<string, string>();
            values.Add("Album Name", albumName);
            values.Add("Include Albums", includeAlbums.ToG2Value());
            values.Add("Random", random.ToG2Value());
            if (limit > 0)
            {
                values.Add("Limit", limit.ToString(CultureInfo.CurrentCulture));
            }

            values.Add("Extra Fields", extraFields.ToG2Value());
            values.Add("All Sizes", allSizes.ToG2Value());

            return new FetchAlbumImagesResponse(this.request.Execute(Commands.FetchImages, values, authToken));
        }

        /// <summary>
        /// Downloads the raw image to a local file.
        /// </summary>
        /// <param name="image">The image.</param>
        /// <param name="fileName">Name of the file.</param>
        public void DownloadRawImage(Image image, string fileName)
        {
            using (WebClient downloadImageClient = new WebClient())
            {
                downloadImageClient.DownloadFile(this.host + image.RawImageUrl, fileName);
            }
        }

        /// <summary>
        /// Fetches the albums that the user can write to.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <returns>A FetchAlbumResponse containing the responses/details.</returns>
        public FetchAlbumResponse FetchAlbumsPrune(string authToken)
        {
            return this.FetchAlbumsPrune(authToken, true);
        }

        /// <summary>
        /// Fetches the albums prune.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <param name="excludeAlbumPermissions">if set to <c>true</c> [exclude album permissions].</param>
        /// <returns></returns>
        public FetchAlbumResponse FetchAlbumsPrune(string authToken, bool excludeAlbumPermissions)
        {
            Dictionary<string, string> values = new Dictionary<string, string>();
            values.Add("Exclude Album Permissions", excludeAlbumPermissions.ToG2Value());
            return new FetchAlbumResponse(this.request.Execute(Commands.FetchAlbumsPrune, values, authToken));
        }

        /// <summary>
        /// Gets the album properties.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <param name="albumName">Name of the album.</param>
        /// <returns>A AlbumPropertiesResponse containing the responses/details.</returns>
        public AlbumPropertiesResponse GetAlbumProperties(string authToken, string albumName)
        {
            Dictionary<string, string> values = new Dictionary<string, string>();
            values.Add("Album Name", albumName);
            return new AlbumPropertiesResponse(this.request.Execute(Commands.AlbumProperties, values, authToken));
        }

        /// <summary>
        /// Creates a new album.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <param name="newAlbumName">New name of the album.</param>
        /// <param name="parentAlbumName">Name of the parent album.</param>
        /// <param name="albumTitle">The album title.</param>
        /// <param name="albumDescription">The album description.</param>
        /// <returns>A NewAlbumResponse containing the responses/details.</returns>
        public NewAlbumResponse NewAlbum(string authToken, string newAlbumName, string parentAlbumName, string albumTitle, string albumDescription)
        {
            Dictionary<string, string> values = new Dictionary<string, string>();
            values.Add("Album Name", newAlbumName);
            values.Add("Parent Album Name", parentAlbumName);
            values.Add("Album Title", albumTitle);
            values.Add("Album Description", albumDescription);
            return new NewAlbumResponse(this.request.Execute(Commands.NewAlbum, values, authToken));
        }

        /// <summary>
        /// Moves the album.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <param name="sourceAlbum">The source album.</param>
        /// <param name="destinationAlbum">The destination album.</param>
        /// <returns>A MoveAlbumResponse containing the responses/details</returns>
        public MoveAlbumResponse MoveAlbum(string authToken, string sourceAlbum, string destinationAlbum)
        {
            Dictionary<string, string> values = new Dictionary<string, string>();
            values.Add("Source Album", sourceAlbum);
            values.Add("Destination Album", destinationAlbum);
            return new MoveAlbumResponse(this.request.Execute(Commands.MoveAlbum, values, authToken));
        }

        /// <summary>
        /// Increments the view count.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <param name="itemId">The item id.</param>
        /// <returns>A IncrementViewCountResponse containing the responses/details</returns>
        public IncrementViewCountResponse IncrementViewCount(string authToken, string itemId)
        {
            Dictionary<string, string> values = new Dictionary<string, string>();
            values.Add("Item Id", itemId);
            return new IncrementViewCountResponse(this.request.Execute(Commands.IncrementViewCount, values, authToken));
        }

        /// <summary>
        /// Gets the image properties.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <param name="itemId">The item id.</param>
        /// <returns>A ImagePropertiesResponse containing the responses/details</returns>
        public ImagePropertiesResponse GetImageProperties(string authToken, string itemId)
        {
            Dictionary<string, string> values = new Dictionary<string, string>();
            values.Add("Item Id", itemId);
            return new ImagePropertiesResponse(this.request.Execute(Commands.ImageProperties, values, authToken));
        }

        /// <summary>
        /// Adds the item from a URL.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <param name="albumName">Name of the album.</param>
        /// <param name="userFile">The user file.</param>
        /// <param name="caption">The caption.</param>
        /// <returns></returns>
        public AddItemResponse AddItemUrl(string authToken, string albumName, Uri userFile, string caption)
        {
            return this.AddItemUrl(authToken, albumName, userFile, caption, string.Empty, false, null);
        }

        /// <summary>
        /// Adds the item from a URL.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <param name="albumName">Name of the album.</param>
        /// <param name="userFile">The user file.</param>
        /// <param name="caption">The caption.</param>
        /// <param name="forceFileName">The force filename.</param>
        /// <param name="autoRotate">if set to <c>true</c> [auto rotate].</param>
        /// <param name="extraFields">The extra fields.</param>
        /// <returns></returns>
        public AddItemResponse AddItemUrl(string authToken, string albumName, Uri userFile, string caption, string forceFileName, bool autoRotate, Dictionary<string, string> extraFields)
        {
            Dictionary<string, string> values = new Dictionary<string, string>();
            values.Add("Album Name", albumName);
            values.Add("User file", userFile.AbsoluteUri);
            values.Add("Caption", caption);
            values.Add("Force Filename", forceFileName);
            values.Add("Auto Rotate", autoRotate.ToG2Value());
            foreach (KeyValuePair<string, string> extraField in extraFields)
            {
                values.Add(String.Format(CultureInfo.CurrentCulture, "extrafield.{0}", extraField.Key), extraField.Value);
            }
            return new AddItemResponse(this.request.Execute(Commands.AddItemUrl, values, authToken));
        }

        /// <summary>
        /// Adds the item by uploading.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <param name="albumName">Name of the album.</param>
        /// <param name="fileName">Name of the file.</param>
        /// <param name="caption">The caption.</param>
        /// <returns></returns>
        public AddItemResponse AddItemUpload(string authToken, string albumName, string fileName, string caption)
        {
            return this.AddItemUpload(authToken, albumName, fileName, caption, string.Empty, false, null);
        }

        /// <summary>
        /// Adds the item by uploading.
        /// </summary>
        /// <param name="authToken">The auth token.</param>
        /// <param name="albumName">Name of the album.</param>
        /// <param name="fileName">Name of the file.</param>
        /// <param name="caption">The caption.</param>
        /// <param name="forceFileName">The force filename.</param>
        /// <param name="autoRotate">if set to <c>true</c> [auto rotate].</param>
        /// <param name="extraFields">The extra fields.</param>
        /// <returns></returns>
        public AddItemResponse AddItemUpload(string authToken, string albumName, string fileName, string caption, string forceFileName, bool autoRotate, Dictionary<string, string> extraFields)
        {
            Dictionary<string, string> values = new Dictionary<string, string>();
            values.Add("Album Name", albumName);
            values.Add("User file", fileName); //HACK
            values.Add("Caption", caption);
            values.Add("Force Filename", forceFileName);
            values.Add("Auto Rotate", autoRotate.ToG2Value());
            foreach (KeyValuePair<string, string> extraField in extraFields)
            {
                values.Add(String.Format(CultureInfo.CurrentCulture, "extrafield.{0}", extraField.Key), extraField.Value);
            }
            return new AddItemResponse(this.request.Execute(Commands.AddItemUrl, values, authToken));
        }
    }
}
